package com.yihen.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.yihen.dto.GoodsDTO;
import com.yihen.dto.OrderDTO;
import com.yihen.util.LevelCheck;
import com.yihen.vo.OrderVO;
import com.yihen.dto.Result;
import com.yihen.mappers.OrderMapper;
import com.yihen.pojo.Order;
import com.yihen.service.GoodsService;
import com.yihen.service.OrderService;
import com.yihen.util.IdWorker;
import com.yihen.util.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;

@Service
@Slf4j
public class IOrderService implements OrderService {
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private OrderMapper orderMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private GoodsService goodsService;

    // 阻塞队列
    private BlockingQueue<OrderVO> orderTasks = new ArrayBlockingQueue<>(1024 * 1024);

    // 线程池
    private static final ExecutorService GOODS_EXECUTOR = Executors.newSingleThreadExecutor();

    @PostConstruct
    private void init() {
        GOODS_EXECUTOR.submit(new OrderHandler());
    }
    private class OrderHandler implements Runnable{
        @Override
        public void run() {
            while (true) {
                try {
                    // 获取order
                    OrderVO order = orderTasks.take();
                    if (order.getStatus().equals("已提交")){
                        goodsService.updateGoodsStatus(order.getGoodsId(), "待交易");
                        Order order1 = BeanUtil.copyProperties(order, Order.class);
                        // 写入数据库
                        orderMapper.insertOrder(order1);
                        orderMapper.insertOrderGoods(order.getGoodsId(), order.getOrderId());
                    } else if (order.getStatus().equals("已完成")) {
                        Long orderId = order.getOrderId();
                        Long goodsId = orderMapper.queryGoodsIdByOrderId(orderId);
                        goodsService.updateGoodsStatus(goodsId, "已卖出");

                    }
                } catch (InterruptedException e) {

                }
            }
        }
    }


    // 加载lua脚本
    private static final DefaultRedisScript<Long> ORDER_SCRIPT;
    static {
        ORDER_SCRIPT = new DefaultRedisScript<>();
        ORDER_SCRIPT.setLocation(new ClassPathResource("order.lua"));
        ORDER_SCRIPT.setResultType(Long.class);

    }


    @Override
    public Result createOrder(Long goodsId) {
            Long id = UserHolder.getUser().getUserId();
        Result result = goodsService.selectGoodsByGoodsId(goodsId);
        GoodsDTO data = (GoodsDTO) result.getData();
        if (data.getUserId().equals(id)) {
            return new Result(false, "无法购买自己发布的商品");
        }
        // 判断是否创建订单
            // 1. 执行lua脚本
            Long res = stringRedisTemplate.execute(ORDER_SCRIPT,
                    Collections.emptyList(),
                    goodsId.toString(), id.toString());

            if (res.equals(2L)) {
                return new Result("其他人已经下单了！");
            }
            else if(res.equals(0L)){
                // 生成订单id
                long orderId = IdWorker.getId();
                stringRedisTemplate.opsForHash().put("order:goods:"+goodsId.toString(),"userId",id.toString());
                stringRedisTemplate.opsForHash().put("order:goods:"+goodsId.toString(),"orderId",Long.toString(orderId));
                // 设置订单过期时间
//                stringRedisTemplate.expire("order:goods:" + goodsId.toString(), 2, TimeUnit.MINUTES);


                OrderVO orderVO = new OrderVO();
                // 设置订单号
                orderVO.setOrderId(orderId);
                // 设置购买人id
                orderVO.setUserId(id);
                // 设置订单状态
                orderVO.setStatus("已提交");
                // 设置订单时间
                orderVO.setDatetime(new Date());
                // 设置订单对于商品
                orderVO.setGoodsId(goodsId);

                orderTasks.add(orderVO);
                log.info("用户:{} 下单商品-{}", UserHolder.getUser().getUserId().toString(),goodsId);
                return new Result(true, orderId);
            }else{
                Long orderId =(Long) redisTemplate.opsForHash().get("order:goods:"+goodsId.toString(), "orderId");
                return new Result(true, orderId);
            }

    }

    @Override
    public Result getMyBuyOrder() {
        Long userId = UserHolder.getUser().getUserId();
        List<OrderDTO> orderDTOS = orderMapper.queryMyBuyOrders(userId);
        changeDealWay(orderDTOS);
        return new Result(true, orderDTOS);
    }

    @Override
    public Result getMySellOrder() {
        Long userId = UserHolder.getUser().getUserId();
        List<OrderDTO> orderDTOS = orderMapper.queryMySellOrders(userId);
        changeDealWay(orderDTOS);
        return new Result(true, orderDTOS);
    }

    @Override
    public Result completeOrder(Long orderId,int appraise)
 {
        Long userId = UserHolder.getUser().getUserId();
        orderMapper.updateOrderStatusAndAppraise(userId, orderId, "已完成",appraise);
        OrderVO orderVO = new OrderVO();
        orderVO.setStatus("已完成");
        orderVO.setOrderId(orderId);
        orderVO.setAppraise(appraise);
        orderTasks.add(orderVO);
     log.info("用户:{} 完成订单-{}",UserHolder.getUser().getUserId().toString(),orderId);

        return new Result(true, "已完成交易");
    }

    @Override
    public Result cancelOrder(Long orderId) {
        // TODO 权限控制
        Long goodsId = orderMapper.queryGoodsIdByOrderId(orderId);
        stringRedisTemplate.delete("order:goods:" + goodsId.toString());
        orderMapper.deleteOrderGoodsByOrderId(orderId);
        orderMapper.deleteOrderByOrderId(orderId);
        goodsService.updateGoodsStatus(goodsId, "已审核");
        log.info("用户:{} 取消订单-{}",UserHolder.getUser().getUserId().toString(),orderId);
        return new Result(true, "取消成功！");
    }

    @Override
    public Result selectOrderByOrderId(int mode,String orderId) {
        Long id;
        try {
            id = Long.valueOf(orderId);
        } catch (Exception e) {
            return new Result("请输入正确格式的订单id");
        }

        Long userId = UserHolder.getUser().getUserId();
        List<OrderDTO> orderDTOS=null;
        // 查询买入
        if (mode == 1) {
            orderDTOS=orderMapper.queryBuyOrdersByOrderId(id, userId);
        } else if (mode == 2) { // 查询卖出
            orderDTOS=orderMapper.querySellOrdersByOrderId(id, userId);
        } else if (mode == 3) {
            orderDTOS= orderMapper.queryOrdersByOrderId(id);
            return new Result(true,orderDTOS);
        }
        changeDealWay(orderDTOS);
        return new Result(true,orderDTOS);
    }

    @Override
    public Result getAllOrders() {
        int level = UserHolder.getUser().getLevel();
        Result result = LevelCheck.levelIsOK(2, "无法管理订单!");
        if (!result.isFlag()) {
            return result;
        }
        List<OrderDTO> orderDTOS = orderMapper.queryAllOrders();
        return new Result(true, orderDTOS);
    }

    @Override
    public Result resetAppraise(Long orderId) {
        int level = UserHolder.getUser().getLevel();
        Result result = LevelCheck.levelIsOK(2, "无法重置评价!");
        if (!result.isFlag()) {
            return result;
        }
        orderMapper.updateOrderStatusTo0(orderId);
        log.info("用户:{} 重置订单-{}评价",UserHolder.getUser().getUserId().toString(),orderId);
        return new Result(true, "重置成功");
    }


    private static void changeDealWay(List<OrderDTO> orders) {
        for (OrderDTO order : orders) {
            if (order.getDealWay().equals("M")) {
                order.setDealWay("金钱交易");
            } else {
                order.setDealWay("以物易物");
            }
        }
    }
}
